home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 43
/
Amiga Format CD43 (1999)(Future Publishing)(GB)(Track 1 of 2)[!][issue 1999-09].iso
/
-in_the_mag-
/
banging_the_metal
/
peek+poke
/
peek+poke.asm
< prev
next >
Wrap
Assembly Source File
|
1999-04-03
|
24KB
|
1,027 lines
* POKES.ASM - dangerous shell commands to examine and modify memory contents.
* Written in HiSoft Devpac 3.14, ver 1.5, March 1997; requires WB 2 or above.
* Copyright 1995-96 SNG, freely distributable; you use this at your own risk.
* Version 1.5 is a maintenance release for Aminet with minor source tweaks.
* Updates since version 1.3:
*
* Uses Tadek Knapik's AnyLongToString to write numbers in hex and binary.
* Appends a new line character to the output of PEEK.
* Allows BINARY as a synonym for BIN and H as a short form for HEX.
* Supports addresses and values in hex or binary as well as decimal.
* Closes DOS.LIBRARY even if READARGs fails.
* Suppresses leading zeroes in hexadecimal and binary output.
* Supports PEEK (but not POKE?) STRING argument.
* Supports AT for indirect addressing, to save extra PEEK LONGs.
* To do:
*
* Support for output of SIGNED values?
* Allow task=task-name argument to access task-relative data?
* Overview:
*
* These commands were written for three purposes:
* (1) To allow low-level access to hardware and memory, from the CLI.
* (2) To prevent the need to write little bits of code for each POKE.
* (3) To experiment with some non-trivial ReadArgs parameter parsing.
* (0) To annoy people who believe that POKEs are a thing of the past.
* Features:
* Can POKE or PEEK a byte, word or long word at any 32 bit memory address.
* Supports signed or unsigned decimal values, reduced MOD size if necessary.
* Addressing can be relative to the base of any library, device or resource,
* or relative to CUSTOM (the base of the Amiga custom chips), CIAA or CIAB.
* Absolutely no protection so you can POKE anything anywhere. Caveat POKEr!
* Typical uses: in general these are not endorsed by Amiga Technology, and
* library, device and resource offsets can vary between software releases.
* These examples show the flexible format of various acceptable parameters:
* POKE ciaa 0 2 - Turns the audio filter off
* POKE CIAA 0 0 - Turns the audio filter on
* PEEK L 4 - Returns the EXEC library base address
* PEEK CUSTOM 18 - Controller 0 left paddle position
* PEEK CUSTOM 19 - Controller 0 right paddle position
* PEEK Res potgo WORD 20 - Version number of POTGO.RESOURCE
* peek word lib dos 22 - Revision number of DOS.LIBRARY
* peek lib exec long 42 - Contents of EXEC cold-capture vector
* POKE CUSTOM WORD 48 511 - Sends MIDI RESET to the serial port
* POKE WORD dev="narrator" 48 90 - Sets speech rate to 90 words/minute
* peek LONG lib "graphics" 50 - Address of current Copper List
* POKE W DEV "narrator" 54 1 - Narrator attempts a female voice
* peek lib="exec" 62 long - Returns the top of Chip Memory
* peek 62 word lib graphics - Returns the current screen display mode
* poke w Dev narrator 62 16 - Set -12 dB Narrator speech volume
* PEEK W lib "graphics" 232 - Microseconds per scan line * 256
* peek lib graphics.library 236 - ChipSet revision, e.g. OCS/ECS/AGA
* POKE CIAB 256 119 - Start motor of DF0, stop other drives
* poke 256 129 ciab - Stop all floppy disk drive motors
* PEEK long library "exec" 276 - Returns base address of this task
* peek LIBRARY="exec" w 296 - Returns ATTN_FLAGS (CPU type)
* POKE LIB "exec.library" 297 1 - Pretend this CPU is a 68010!
* Peek LIB "exec" 530 - Returns the vertical blanking frequency
* PEEK 531 lib exec - Returns power supply frequency in Hertz
* PEEK LONG Library "exec" 568 - Number of timer 'E clocks' per second
* PEEK CIAB 2048 - Low byte of 24 bit scan-line counter
* PEEK dev=parallel string long 10 - "parallel.device", or "pit.device" if
* MapDevice parallel 0 to pit 0 is active.
* See Mapping The Amiga, The Amiga Guru Book and the CBM Includes for lots
* more interesting and dangerous offsets. The best and most hazardous ones
* are secret. If you're not sure, PEEK first and POKE afterwards (perhaps)!
* Notes on parameter and result handling:
* You may specify the transfer size and device/resource/library/hardware
* base in any order, so PEEK WORD CUSTOM 18 means the same as PEEK 18 WORD
* CUSTOM or PEEK W 18 CUSTOM or PEEK CUSTOM WORD 18. The choice is yours.
* Unfortunately qualifiers (LIB, LIBRARY, RES, DEVICE etc) must appear just
* before the name of the library, resource or device which you want to use,
* so you need to say PEEK LIB exec 530 as PEEK exec LIB 530 will not work.
* The Device option always selects unit zero, with 0 in the 'flags' field.
* Combinations of switches are additive, so PEEK LIB exec CUSTOM 2 reads
* the byte at ExecBase + $DFF000 + 2, which is unlikely to be very useful.
* The AT parameter indicates indirect addressing. The long word at the
* specified address is read and used as a pointer to the required data.
* Absolutely no validity checks are performed.
* Numeric values may be specified in decimal, binary with a % prefix, or
* hexadecimal if prefixed with $, 0X or 0x. Excessive values are reduced
* modulo the transfer size, e.g. POKE 0 $123 stores $23 and POKE WORD 0
* $123456 stores $3456. Thus conventional (decimal only) ReadArgs numeric
* parsing cannot be used for value and address arguments, so the /N does
* not appear in the argument template. Nonetheless, VALUE and ADDRESS
* arguments are numeric.
* By default PEEK returns a decimal number, but it can be a string up to
* 32 bytes long (stopping after 32 bytes or at the first null) returned
* in quotes, if the STRING switch is supplied, a value in binary, or in
* hexadecimal, indicated by the HEX or H switch and $ prefix before the
* number for base 16. The BIN or BINARY switch sets base 2 and a % prefix.
* The STRING parameter expects that the argument is the offset of a pointer
* to the required string rather than the offset of the start of the string.
* Numeric parameters are 32 bit signed or unsigned decimal values. Results
* are unsigned bytes or words, signed long words. The default data size is
* BYTE - this is not a switch. Words and bytes are reduced modulo 65536 and
* modulo 256 respectively. Device, Resource and library names are case-
* sensitive and the .suffix is assumed if not explicitly presented. All
* other keywords are case-insensitive. Quotes, verbose qualifiers and
* equals signs are optional. PEEK returns an ASCII string followed by
* a trailing space and a newline, or nothing if an error occurs. You
* can redirect this to an environment variable and use its value later
* in your shell script. For instance, this code checks the current CPU
* and writes an appropriate message if it's a 68040 and 68060:
* PEEK lib=exec 297 >env:CPU
* IF $CPU equ 127
* ECHO "68040 processor"
* ELSE
* IF $CPU equ 255
* ECHO "68060 processor"
* ENDIF
* ENDIF
* EVAL can be used with PEEK environment variables. For instance this
* sequence finds the start address of any Commodore Kickstart ROM:
* PEEK LONG $FFFFEC >env:ROMsize
* EVAL 65536*256-$ROMsize
* There is currently no check for uneven-addressed words or long words,
* which cause an odd address guru on 68000/68010 systems but work fine
* on later processors, including all the current 32 bit Amiga models.
* Attempts to access non-existent memory on a Zorro 3 Amiga cause a bus
* error after a delay of a fraction of a second, unless remapped by MMU.
* Source organisation:
* No include files are needed as all necessary constants are in this file.
* This stand-alone source file includes the code for PEEK as well as POKE.
* Choose the one you want by setting PEEK equ 0 for POKE, PEEK=1 for PEEK.
PEEK equ 1
MaxName equ 64 Limit total length of name
* EXEC.LIBRARY jump table offsets
CloseLibrary equ -414
OpenDevice equ -444
CloseDevice equ -450
OpenResource equ -498
OpenLibrary equ -552
* DOS.LIBRARY jump table offsets
ReadArgs equ -798
FreeArgs equ -858
VPrintf equ -954
* Offsets for ReadArgs results
WordSize equ 0
LongSize equ 4
LibName equ 8
DevName equ 12
ResName equ 16
Custom equ 20
CIAA equ 24
CIAB equ 28
AT equ 32 Indirect address
ifeq PEEK
Address equ 36
Value equ 40
else
Hex equ 36 Return hexadecimal with $ prefix
Bin equ 40 Return binary number with % prefix
String equ 44 Return quoted ASCII string
Address equ 48
endc
SECTION INSTRUCTIONS,CODE
Start move.l 4.w,a6
move.l a6,ExecBase
moveq #37,d0 Version 2.00 +
lea.l DosName,a1
jsr OpenLibrary(a6)
move.l d0,DosBase
beq Fail
move.l d0,a6
move.l #Template,d1
lea.l ArgTable,a2
move.l a2,d2
moveq #0,d3 No explicit RDARGS yet
jsr ReadArgs(a6)
move.l d0,d1
beq LateFail ** 1.4 **
jsr FreeArgs(a6)
move.l ExecBase,a6
move.l Address(a2),a0 Pointer to string
jsr AnyStrToLong
tst.l d1
beq LateFail
move.l d0,a3 Where to PEEK or POKE (or offset)
* Find library base if necessary
move.l LibName(a2),d0
beq.s NotLibrary
lea.l LibSuffix,a0
bsr NameCheck
moveq #0,d0 Any library version
jsr OpenLibrary(a6) Call EXEC
move.l d0,CloseBase
bne.s AddBase
bra LateFail
* Find device base if necessary
NotLibrary move.l DevName(a2),d0
beq.s NotDevice
lea.l DevSuffix,a0
bsr NameCheck
move.l a1,a0 Pointer to device name
move.l #ioRequest,a1
moveq #0,d0 Unit number
moveq #0,d1 No special flags
jsr OpenDevice(a6)
tst.l d0
bne LateFail
move.l #ioRequest,a1
add.l 20(a1),a3 Add base of device structure
move.l a1,CloseBase Store what thou shalt restore
bra.s NotResource
* Track down a resource, if necessary
NotDevice move.l ResName(a2),d0
beq.s NotResource
lea.l ResSuffix,a0
bsr NameCheck
jsr OpenResource(a6) Call EXEC
tst.l d0 No need to store this one
beq LateFail
AddBase add.l d0,a3 Add base to supplied address
* If users mix and match switches, this code just totals ALL the offsets!
NotResource tst.l Custom(a2)
beq.s NotCustom
add.l #$DFF000,a3
NotCustom tst.l CIAA(a2)
beq.s NotCIAA
add.l #$BFE001,a3
NotCIAA tst.l CIAB(a2)
beq.s NotCIAB
add.l #$BFD000,a3
NotCIAB tst.l AT(a2)
beq.s NotAT
move.l (a3),a3 Use indirect address
NotAT
ifeq PEEK
move.l Value(a2),a0 Where to PEEK what to POKE
jsr AnyStrToLong
tst.l d1
beq.s LateFail
else
moveq #0,d0 Clear top bytes of result
endc
tst.l WordSize(a2)
bne.s PokeWord
tst.l LongSize(a2)
bne.s PokeLong
ifeq PEEK
move.b d0,(a3)
bra.s Done
PokeLong move.l d0,(a3) Must be word aligned if < 68020!
bra.s Done
PokeWord move.w d0,(a3) Beware odd alignment on old CPUs
else
move.b (a3),d0
bra.s Return
PokeLong move.l (a3),d0 Must be even boundary if < 68020!
bra.s Return
PokeWord move.w (a3),d0 Odd alignment crashes old CPUs
* Send the result in D0 back to the shell with VPRINTF
Return lea.l Buffer,a0
tst.l String(a2)
beq.s NotString
move.l d0,a1
moveq #32-1,d1 Maximum to write to buffer
move.b #'"',(a0)+
CopyString move.b (a1)+,(a0)+
dbeq d1,CopyString
bne.s Terminate
subq.l #1,a0 Remove trailing null if any
Terminate move.b #'"',(a0)+
clr.b (a0) Terminate with extreme prejudice
bra.s Report
NotString move.l #LTS_DECIMAL,d1
tst.l Hex(a2)
beq.s NotHex
move.l #LTS_HEX,d1
move.b #'$',(a0)+
bra.s Cooked
NotHex tst.l Bin(a2)
beq.s Cooked
move.l #LTS_BINARY,d1
move.b #'%',(a0)+
* bra.s Cooked
Cooked jsr AnyLongToStr
tst.l d0
beq.s LateFail
Report move.l #StrFormat,d1
move.l #Result,d2
move.l #Buffer,Result
move.l DosBase,a6
jsr VPrintf(a6)
endc
* Close whatever library/device/resource we have opened before returning
Done move.l ExecBase,a6
move.l CloseBase,a1
move.l LibName(a2),d0
beq.s LibFree
jsr CloseLibrary(a6)
LibFree move.l DevName(a2),d0
beq.s CloseDOS
jsr CloseDevice(a6)
CloseDOS move.l DosBase,a1
jsr CloseLibrary(a6)
moveq #0,d0
rts
* Direct exit from NameCheck if string is too long for our buffer
LaterFail addq.l #4,a7 Return to prior caller
* Exit used when the program fails after opening DOS.LIBRARY
LateFail move.l DosBase,a1
move.l ExecBase,a6
jsr CloseLibrary(a6)
Fail moveq #30,d0
rts
* Ensure name string at D0 includes a dot, or add the suffix
* at A0. Return A1 pointing to the checked string. Uses A4,D4.
NameCheck moveq #MaxName-1,d1 -1 for DBEQ loops later
lea.l OpenName,a4
move.l d0,a1
Scan move.b (a1)+,d4
cmp.b #'.',d4
beq.s GotDot
move.b d4,(a4)+
dbeq d1,Scan Continue till null or D1=-1
bne.s LaterFail
subq.l #1,a4 Step back over dot
addq.w #1,d1 Adjust limit count
Append move.b (a0)+,(a4)+
dbeq d1,Append
bne.s LaterFail We never reached the null!
lea.l OpenName,a1 Point at start of our copy
rts
GotDot move.l d0,a1 Use the literal string
rts
SECTION TADEK,CODE
**********************************************************************
*
* AnyStrToLong - convert ASCII string to 32-bit value
*
* Input: a0 - null terminated string
* Output: d0 - the value (was $FFFFFFFF if error - removed by SNG)
* d1 - success (boolean)
*
* As string you can pass decimal (no prefix), binary (prefix '%')
* or hex (prefixes '$' or '0x'). Check d1 for success or failure (fails
* when non-specific characters are found, or if null string).
* In hex/bin mode, when you pass too many characters, only last
* 8/32 are used. In dec mode, maximal value is 4.294.967.295
* ($FFFFFFFF). Decimal values may be negative (prefix '-'), then the
* range is from -2.147.483.647 to 2.147.483.648 (otherwise the result
* is not reliable).
*
* Alters only scratch registers (d0, d1, a0, a1). Uses 16 bytes
* of stack (decimal mode only).
*
*
* © 1996 by Tadek Knapik (tadek@student.uci.agh.edu.pl).
* Public Domain. E-mail appreciated :-)
*
**********************************************************************
AnyStrToLong:
;; cmpi.b #0,(a0) ;null string?
tst.b (a0) ;; SNG - faster
beq.s AnyStrToLongError
moveq #0,d0 ;negative flag in decimal mode
cmpi.b #'-',(a0) ;negative?
beq DecStrToLong0
cmpi.b #'%',(a0) ;binary?
beq.s BinStrToLong0 ;yes!
cmpi.b #'$',(a0) ;hex
beq.s HexStrToLong0 ;yes!
cmpi.b #'0',(a0) ;hex (0x)
bne DecStrToLong ;no!
movea.l a0,a1 ;string pointer
adda.l #1,a1
cmpi.b #'X',(a1) ;; Capital check, SNG
beq.s Prefix0X
cmpi.b #'x',(a1) ;'x'?
bne.s DecStrToLong ;
Prefix0X addq.l #1,a0 ;;omit '0' (Q not A)
;; bra.s HexStrToLong
;--------------------
;convert hex to long.
HexStrToLong0:
addq.l #1,a0 ;;next byte (omit '$/x/X')
HexStrToLong:
moveq #0,d0
moveq #0,d1
HexNextNybble:
tst.b (a0) ;;the end?
beq.s AnyStrToLongEnd ;yes
;next character
lsl.l #4,d0 ;prepare next 4 bits
;; moveq #0,d1 ;clr = redundant, SNG
move.b (a0)+,d1 ;next cipher
cmpi.b #'0',d1 ;lower than 0?
blt.s AnyStrToLongError
cmpi.b #'f',d1 ;higher than f?
bgt.s AnyStrToLongError
subi.b #'0',d1 ;ASCII '0'
bmi.s AnyStrToLongError
;now we have 0-9. Or not..
cmpi.b #9,d1 ;more than '9'?
ble.s HexReady ;no, we're done
subq.b #7,d1 ;;try this
;If A-F, we have 10-15, unless <, >, @ etc., or a-f
cmpi.b #10,d1 ;less than 'A'?
blt.s AnyStrToLongError ;yes, jump @ Error
cmpi.b #15,d1 ;more than 'F'
ble.s HexReady ;OK
;so, probably a-f
subi.b #32,d1 ;case change?
cmpi.b #10,d1 ;less?
blt.s AnyStrToLongError ;yes, probably XYZ
cmpi.b #15,d1 ;more than 'f'
ble.s HexReady ;no, OK
bra.s AnyStrToLongError ;error, probably xyz
;in d1 we have value in range 0-15
HexReady:
or.b d1,d0 ;set those bits
bra.s HexNextNybble ;next one, please
AnyStrToLongError:
;; moveq #-1,d0 ;;if -1 in d0, then
moveq #0,d1 ;d1 is boolean failure
rts
AnyStrToLongEnd:
moveq #1,d1
rts
;--------------------
;convert binary to long.
BinStrToLong0:
addq.l #1,a0 ;;next byte
BinStrToLong:
tst.b (a0) ;;nothing?
beq.s AnyStrToLongError
moveq #0,d0
moveq #0,d1
BinNextBit:
;; cmpi.b #0,(a0) ;coô jeszcze
tst.b (a0) ;;faster
beq AnyStrToLongEnd
;what do we have here..
lsl.l #1,d0 ;prepare next bit
moveq #0,d1
move.b (a0)+,d1
subi.b #'0',d1
bmi.s AnyStrToLongError
cmpi.b #1,d1 ;more than 1?
bgt.s AnyStrToLongError
;now we have 0 or 1 in d1.
or.b d1,d0 ;to set or not to set
bra.s BinNextBit
;--------------------
;Convert decimal ASCII to 32 bit long.
;Maximum - 4.294.967.295 ($FFFFFFFF)
;If you pass in [x*4.294.967.295+y], it will probably return [y].
DecStrToLong0:
addq.l #1,a0 ;;next byte (omit '-')
moveq #1,d0
DecStrToLong:
tst.b (a0) ;;nic?
beq.s AnyStrToLongError
movem.l d2-d5,-(sp)
move.l d0,d5 ;negative flag
moveq #0,d1 ;clr
moveq #0,d0 ;the value
movea.l a0,a1 ;string
addq.l #1,a1 ;;cause I add immediately
;length of the string without last null character
DecStrLengthLoop:
addq.l #1,d1
tst.b (a1)+
bne.s DecStrLengthLoop
;now in d1 we have the weight of the first cipher plus 1
DecNextCipherLoop:
subq.l #1,d1 ;sub 1
tst.l d1 ;if null, this is the last one
beq.s DecLastCipher
move.l d1,d2
moveq #0,d3
move.b (a0)+,d3 ;the cipher
subi.b #'0',d3
bmi.s DecStrToLongError
cmpi.b #9,d3
bgt.s DecStrToLongError
DecMultipleLoop:
move.l d3,d4 ;copy it
lsl.l #3,d3 ;*8
lsl.l #1,d4 ;*2
add.l d4,d3 ;x*2+x*8=x*(2+8)=x*10
subq.l #1,d2
bne.s DecMultipleLoop
add.l d3,d0
bra.s DecNextCipherLoop
DecLastCipher:
moveq #0,d3
move.b (a0)+,d3
subi.b #'0',d3
bmi.s DecStrToLongError
cmpi.b #9,d3
bgt.s DecStrToLongError
add.l d3,d0
DecStrToLongEnd:
tst.l d5 ;was it negative?
beq.s DecStrToLongPositiveEnd
neg.l d0 ;negate it
DecStrToLongPositiveEnd:
movem.l (sp)+,d2-d5
bra AnyStrToLongEnd
DecStrToLongError:
movem.l (sp)+,d2-d5
bra AnyStrToLongError
ifne PEEK
**********************************************************************
*
* AnyLongToStr - Convert 32-bit value to ASCII
*
* Input: d0 - the value to convert
* d1 - flags
* a0 - pointer to a buffer
* Output: d0 - number of characters written (or null for error)
* a0 - address of the terminating null
*
*
* Flags are:
* LTS_DECIMAL - normal decimal conversion
* LTS_SIGN_LONG - decimal signed mode (longword)
* LTS_SIGN_WORD - signed (word)
* LTS_SIGN_BYTE - signed (byte)
* LTS_BINARY - convert to binary
* LTS_HEX_UPPER - convert to hex (A-F)
* LTS_HEX_LOWER - convert to hex (a-f)
*
*
* You should pass a buffer with at least 11/12 (decimal/negative
* decimal), 9 (hex) or 33 (binary) bytes of space.
* If flags = #1, checks the 31 bit and if it is high, assumes
* the value is lower than 0.
* This string is null-terminated. Address of the terminating
* null is returned in a0. The null is included in number of chars
* written.
*
* When you specify decimal non-signed mode, then even if
* bit 31 is set you'll get value in range 0 to 4.294.967.295. In
* signed mode you'll get values in range from -2.147.483.647 to
* 2.147.483.648 (negative when bit 31/15/7 is set, depending on the
* choosen mode). Minus sign is written, if needed (and added to chars
* counter returned in d0).
*
* No prefix is written in hex/bin mode!!! If you need it, write
* it yourself. That's how you can choose between '$'/'0x' :-)
*
* Alters only scratch registers (d0, d1, a0, a1). Uses 12 bytes
* of stack.
*
*
* © 1996 by Tadek Knapik (tadek@student.uci.agh.edu.pl).
* Public Domain. E-mail appreciated :-)
*
**********************************************************************
LTS_DECIMAL equ 0
LTS_BINARY equ 2
LTS_HEX_UPPER equ 4
LTS_HEX_LOWER equ 8
LTS_SIGN_LONG equ 16
LTS_SIGN_WORD equ 32
LTS_SIGN_BYTE equ 64
LTS_NEGATIVE equ LTS_SIGN_LONG
LTS_HEX equ LTS_HEX_UPPER
AnyLongToStr:
movem.l d2-d4,-(sp)
moveq #0,d2 ;the counter
cmpi.l #LTS_DECIMAL,d1
beq.s LTSDecConvert
cmpi.l #LTS_SIGN_LONG,d1
beq.s LTSMinDecConvert
cmpi.l #LTS_SIGN_WORD,d1
beq.s LTSMinWDecConvert
cmpi.l #LTS_SIGN_BYTE,d1
beq.s LTSMinBDecConvert
cmpi.l #LTS_BINARY,d1
beq LTSBinConvert
move.l #'A',d2 ;ASCII base uppercased
cmpi.l #LTS_HEX_UPPER,d1
beq LTSHexConvert
move.l #'a',d2 ;ASCII base lowercased
cmpi.l #LTS_HEX_LOWER,d1
beq LTSHexConvert
LTSError:
movem.l (sp)+,d2-d4
moveq #0,d1
moveq #0,d0
rts
;--------------------
LTSMinBDecConvert:
ext.w d0 ;extend to word
LTSMinWDecConvert
ext.l d0 ;extend to longword
LTSMinDecConvert:
btst #31,d0
beq.s LTSDecConvert
move.b #'-',(a0)+ ;the minus sign
addq.l #1,d2
neg.l d0 ;so I need plus now
LTSDecConvert:
moveq #0,d1 ;zeroes flag
move.l #1000000000,d4 ;32-bit max power of 10
LTSDecAgain:
cmp.l d4,d0
bcc.s LTSDecMatch
tst.l d1 ;write zeroes?
beq.s LTSDecNextPass ;not yet
move.b #'0',(a0)+ ;write it
addq.l #1,d2 ;one character more
bra.s LTSDecNextPass
LTSDecMatch:
moveq #1,d1 ;means write zeros from now
moveq #0,d3 ;clear temporary
LTSDecLoop:
addq.l #1,d3
sub.l d4,d0
bpl.s LTSDecLoop ;branch if not less than 0
add.l d4,d0 ;did it too many times
subq.l #1,d3 ;as well
addi.l #'0',d3 ;ASCII 0
move.b d3,(a0)+
addq.l #1,d2 ;the counter
LTSDecNextPass:
bsr.s LTSDecDivideByTen
tst.l d4
beq.s LTSError
cmpi.l #1,d4
bne.s LTSDecAgain
;less than 10 in d0..
addi.l #'0',d0
move.b d0,(a0)+
addq.l #1,d2
LTSDecOver:
move.b #0,(a0)
suba.l #1,a0
addq.l #1,d2 ;null is a character, too
move.l d2,d0
movem.l (sp)+,d2-d4
rts
LTSDecDivideByTen:
;
;if your proggy is to be run on 020+ only!
;
; mulu.l #10,d4
; rts
;now 68000 part. Thanks for Simon N Goodwin for this routine!
moveq #0,d3 ;temporary register
swap d4 ;higher 16 bits
move.w d4,d3
divu #10,d3 ;divide higher 16 bits
swap d3 ;store in high word of d3
move.w d3,d4 ;safe?
swap d4
divu #10,d4 ;divide lower 16 bits
move.w d4,d3
exg d3,d4
rts
;--------------------
; Peephole optimisations and leading zero suppression by SNG
LTSHexConvert:
tst.l d0 ;;Zero is special
bne.s LTSHexSet
LTSzero move.b #'0',(a0)+
bra.s LTSdone
LTSHexSet: moveq #8-1,d4 ;8 characters
LTSHexLoop:
rol.l #4,d0 ;prepare next nybble
moveq #%1111,d1 ;; mask quick load
and.l d0,d1 ;the nybble
beq.s LTSHexTry
bset #31,d4 ;;Flag zero found
LTSHexTry tst.l d4 ;; Any zeroes yet?
bpl.s LTSHexNxt
moveq #'0',d3 ;ASCII base (for 0-9)
cmpi.l #9,d1 ;normal or a-f
ble.s LTSHexDec
move.l d2,d3 ;new base (A-F or a-f)
subi.l #$A,d1 ;new value :-)
LTSHexDec:
add.l d1,d3 ;add soup base, cover it and
move.b d3,(a0)+ ;wait for 3 minutes :-)
LTSHexNxt: dbra d4,LTSHexLoop
LTSdone: clr.b (a0) ;terminate
suba.l #1,a0
movem.l (sp)+,d2-d4 ;give it back..
moveq #9,d0 ;no way for 8 :-)
rts
;--------------------
LTSBinConvert:
moveq #32-1,d4 ;;DBRA 32 characters
tst.l d0
beq.s LTSzero
LTSBinLoop:
rol.l #1,d0 ;one bit
moveq #1,d1 ;;spare
and.l d0,d1 ;;the bit
beq.s LTSBinSup
bset #31,d4 ;;Sign
LTSBinSup tst.l d4
bpl.s LTSBinNxt
LTSBinOut add.b #'0',d1
move.b d1,(a0)+
LTSBinNxt dbra d4,LTSBinLoop ;;do it again
bra.s LTSdone
;; clr.b (a0) ;terminate
;; subq.l #1,a0
;; movem.l (sp)+,d2-d4 ;give it back..
;; moveq #33,d0 ;am I sure of that?
;; rts
endc
**********************************************************************
SECTION STRINGS,DATA
Version dc.b '$VER: POKES 37.6 (28/3/97)',0
DosName dc.b 'dos'
LibSuffix dc.b '.library',0
DevSuffix dc.b '.device',0
ResSuffix dc.b '.resource',0
Template dc.b 'W=WORD/S,L=LONG/S,'
Template2 dc.b 'LIB=LIBRARY/K,DEV=DEVICE/K,RES=RESOURCE/K,'
Template3 dc.b 'C=CUSTOM/S,CIAA/S,CIAB/S,AT/S,'
ifeq PEEK
Template4 dc.b 'ADDRESS/A,VALUE/A',0
else
Template5 dc.b 'H=HEX/S,BIN=BINARY/S,STRING/S,ADDRESS/A',0
StrFormat dc.b '%s ',10,0
endc
SECTION VARIABLES,BSS
ExecBase ds.l 1
DosBase ds.l 1
CloseBase ds.l 1 Points at the thing to be closed
ArgTable ds.l Address/4+2
ioRequest ds.l 32 128 bytes should be enough?
OpenName ds.b MaxName Overflows here if necessary
ifne PEEK
Buffer ds.b 36 Not re-entrant
Result ds.l 1 Pointer to buffer
endc
end